#define IO_BUFFER 256
#define BUFFER_SIZE 1024
#define MAX_PLUGIN_ARGUMENTS 32
#define MAX_INPUT_PLUGINS 10
#define MAX_OUTPUT_PLUGINS 10
#define MAX_SD_LEN 50
//#define OUTPUT_PLUGIN_PREFIX " o: "
//#define OPRINT(...) { char _bf[1024] = {0}; snprintf(_bf, sizeof(_bf)-1, __VA_ARGS__); fprintf(stderr, "%s", OUTPUT_PLUGIN_PREFIX); fprintf(stderr, "%s", _bf); syslog(LOG_INFO, "%s", _bf); }



struct user_request
{
	char method[30];   // 요청 방법
	char page[255];    // 페이지 이름
	char http_ver[80]; // HTTP 프로토콜 버전 
};


/* the webserver determines between these values for an answer */
typedef enum { A_UNKNOWN, A_COMMAND, A_FILE } answer_t;



/* the iobuffer structure is used to read from the HTTP-client */
typedef struct {
	int level;              /* how full is the buffer */
	char buffer[IO_BUFFER]; /* the data */
} iobuffer;


/*
* the client sends information with each request
* this structure is used to store the important parts
*/
typedef struct {
	answer_t type;
	char *parameter;
	char *client;
	char *credentials;
} request;


/* store configuration for each server instance */
typedef struct {
	int port;
	char *credentials;
	char *www_folder;
	char nocommands;
} config;

/*
* this struct is just defined to allow passing all necessary details to a worker thread
* "cfd" is for connected/accepted filedescriptor
*/



/* parameters for input plugin */
typedef struct _input_parameter input_parameter;
struct _input_parameter {
	int id;
	char *parameters;
	int argc;
	char *argv[MAX_PLUGIN_ARGUMENTS];
	struct _globals *global;
};


/* parameters for output plugin */
typedef struct _output_parameter output_parameter;
struct _output_parameter {
	int id;
	char *parameters;
	int argc;
	char *argv[MAX_PLUGIN_ARGUMENTS];
	struct _globals *global;
};



/* structure to store variables/functions for output plugin */
typedef struct _output output;
struct _output {
	char *plugin;
	void *handle;
	output_parameter param;

	int (*init)(output_parameter *param, int id);
	int (*stop)(int);
	int (*run)(int);
	int (*cmd)(int plugin, unsigned int control_id, unsigned int group, int value);
};

/* structure to store variables/functions for input plugin */
typedef struct _input input;
struct _input {
	char *plugin;
	void *handle;

	input_parameter param; // this holds the command line arguments

	/* signal fresh frames */
	pthread_mutex_t db;
	pthread_cond_t  db_update;

	/* global JPG frame, this is more or less the "database" */
	unsigned char *buf;
	int size;

	/* v4l2_buffer timestamp */
	struct timeval timestamp;

	int (*init)(input_parameter *, int id);
	int (*stop)(int);
	int (*run)(int);
	int (*cmd)(int plugin, unsigned int control_id, unsigned int group, int value);
};


typedef struct _globals globals;

struct _globals {
	int stop;

	/* input plugin */
	input in[MAX_INPUT_PLUGINS];
	int incnt;

	/* output plugin */
	output out[MAX_OUTPUT_PLUGINS];
	int outcnt;

	/* pointer to control functions */
	//int (*control)(int command, char *details);
};

/* context of each server thread */
typedef struct {
	int sd[MAX_SD_LEN];
	int sd_len;
	int id;
	globals *pglobal;
	pthread_t threadID;

	config conf;
} context;

typedef struct {
	context *pc;
	int fd;
} cfd;


static const struct {
	const char *dot_extension;
	const char *mimetype;
} mimetypes[] = {
	{ ".html", "text/html" },
	{ ".htm",  "text/html" },
	{ ".css",  "text/css" },
	{ ".js",   "text/javascript" },
	{ ".txt",  "text/plain" },
	{ ".jpg",  "image/jpeg" },
	{ ".jpeg", "image/jpeg" },
	{ ".png",  "image/png"},
	{ ".gif",  "image/gif" },
	{ ".ico",  "image/x-icon" },
	{ ".swf",  "application/x-shockwave-flash" },
	{ ".cab",  "application/x-shockwave-flash" },
	{ ".jar",  "application/java-archive" },
	{ ".json", "application/json" }
};





/* prototypes */
void *server_thread(void *arg);
void send_error(int fd, int which, char *message);

//원래 우리
int webserv(int sockfd);
int protocol_parser(char *str, struct user_request *request);
int sendpage(int sockfd, char *filename, char *http_ver, char *codemsg);
int _readline(int fd, iobuffer *iobuf, void *buffer, size_t len, int timeout);
int _read(int fd, iobuffer *iobuf, void *buffer, size_t len, int timeout);
void init_iobuffer(iobuffer *iobuf);
void init_request(request *req);
void free_request(request *req);
void *client_thread(void *arg);
void server_cleanup(void *arg);
void send_file(int id, int fd, char *parameter);
int unescape(char *string);
int hex_char_to_int(char in);
void decodeBase64(char *data);
